package com.tt.payee.controller.login;

import com.google.common.collect.Maps;

import com.tt.payee.api.ResponseResult;
import com.tt.payee.business.AbortException;
import com.tt.payee.common.Constant;
import com.tt.payee.domain.SysUser;
import com.tt.payee.domain.dto.WxParams;
import com.tt.payee.domain.vo.SysUserVo;
import com.tt.payee.service.login.WxLoginService;
import com.tt.payee.service.sysuser.SysUserService;
import com.tt.payee.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import jdk.nashorn.internal.ir.annotations.Reference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @author zhaochongsen
 * @Description: 后台用户登录
 * @date:2020-06-16 10:08
 */
@RestController
@RequestMapping("/terminal/auth")
@Slf4j
@Api(tags = "终端-登录接口")
public class TerminalLoginController {

    @Reference
    SysUserService sysUserService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private WxLoginService wxLoginService;

    /**
     * 获取手机验证码
     *
     * @return
     */
    @RequestMapping(value = "/getValidateCode", method = RequestMethod.POST)
    @ApiOperation(value = "手机验证码")
    public ResponseResult<Object> getValidateCode(@RequestBody SysUserVo sysUserVo) {

        if(StringUtils.isBlank(sysUserVo.getUsername())){
            throw new AbortException("手机号不能为空");
        }

        if(!RegexUtils.checkMobile(sysUserVo.getUsername())){
            throw new AbortException("手机号格式错误");
        }

        ValidateSmsCodeUtil.Validate v = ValidateSmsCodeUtil.getRandomCode(6);
        if (v == null) {
            throw new AbortException("系统繁忙，请稍后再试");
        }

        boolean flag = SmsUtils.sendSms("亲爱的用户，您的验证码是"+v.getValue()+"，5分钟内有效。", sysUserVo.getUsername().trim());
        if(!flag){
            throw new AbortException("发送失败，请稍后再试");
        }
        redisUtils.set(Constant.VALIDATE_CODE+":"+sysUserVo.getUsername(), v.getValue(), Constant.VALIDATE_CODE_EXPIRATION_TIME);

        return ResponseResult.success("发送成功");
    }

    /**
     * 微信小程序授权登录接口
     *
     * @return
     */
    @RequestMapping(value = "/miniAuth", method = RequestMethod.POST)
    @ApiOperation(value = "微信小程序授权登录接口")
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功"),
            @ApiResponse(code = 500, message = "用户已被停用,请联系管理员"),
            @ApiResponse(code = 100101, message = "管理员账号密码错误")
    })
    public ResponseResult<Object> miniAuth(@RequestBody WxParams wxParams) {
        // 返回结果
        Map<String, Object> result = Maps.newHashMap();

        HashMap<String, String> sessionInfo = wxLoginService.getSessionInfo(wxParams.getCode(), wxParams.getEncryptedData(), wxParams.getIv());
        if(sessionInfo == null){
            throw new AbortException("身份信息已过期,请重试");
        }

        SysUser tempUser = new SysUser();
        tempUser.setWxUnionid(sessionInfo.get("unionId"));
        SysUser user = sysUserService.getOne(tempUser);

        if (user != null && user.getStatus().equals(Constant.USER_STATUS_CLOSE)) {
            throw new AbortException("用户已被停用,请联系管理员");
        }

        if (user != null && user.getStatus().equals(Constant.USER_STATUS_DELETE)) {
            throw new AbortException("对不起,您的账号不存在");
        }

        //如果user为空，走注册路径
        if(user==null){
            user = new SysUser();
            user.setTopReferralCode(wxParams.getTopReferralCode());
            user.setWxUnionid(sessionInfo.get("unionId"));
            user.setWxOpenid(sessionInfo.get("openId"));
            user.setWxName(sessionInfo.get("nickName"));
            user.setIsFirst(1);
            user.setIsEngineer(0);
            user.setLoginVersion(0);
            user.setPoint(BigDecimal.valueOf(new Double(500)));
            user.setStatus(1);
            user.setVip(1);
            user = sysUserService.insert(user);

        }

        String token = JwtTokenUtil.generateTerminalUserToken(user);
        result.put("token", token);
        result.put("sessionKey",sessionInfo.get("session"));
        result.put("sysUser",user);

        redisUtils.set(Constant.FRONTEND_TOKEN_PRE+":"+user.getUid(), token, Constant.EXPIRATION_TIME);

        //刷新用户登录时间
        user.setLogindate(new Date());
        sysUserService.update(user);

        return ResponseResult.success("登录成功", result);

    }

    /**
     * 微信小程序授权手机号接口
     *
     * @return
     */
    @RequestMapping(value = "/authPhoneNumber", method = RequestMethod.POST)
    @ApiOperation(value = "小程序授权")
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功"),
            @ApiResponse(code = 500, message = "用户已被停用,请联系管理员"),
            @ApiResponse(code = 100101, message = "管理员账号密码错误")
    })
    public ResponseResult<Object> authPhoneNumber(ServerWebExchange exchange, @RequestBody WxParams wxParams) throws Exception{
        // 返回结果
        Map<String, Object> result = Maps.newHashMap();

        //微信获取用户手机号
        HashMap<String, String> sessionInfo = wxLoginService.getPhone(wxParams.getSessionKey(), wxParams.getEncryptedData(), wxParams.getIv());
        if(sessionInfo == null){
            throw new AbortException("手机授权失败");
        }

        String token = exchange.getRequest().getHeaders().getFirst("access_token");
        Long id = Long.parseLong(JwtTokenUtil.getIdFromToken(token));
        SysUser sysUser = sysUserService.getById(id);
        if(sysUser == null){
            throw new AbortException("用户不存在");
        }
        sysUser.setUsername(sessionInfo.get("phone"));
        sysUser = sysUserService.changeWxPhone(sysUser);

        String newToken = JwtTokenUtil.generateTerminalUserToken(sysUser);
        result.put("token", newToken);
        result.put("sysUser",sysUser);
        redisUtils.set(Constant.FRONTEND_TOKEN_PRE+":"+sysUser.getUid(), newToken, Constant.EXPIRATION_TIME);

        return ResponseResult.success("授权成功", result);

    }

    /**
     * 小程序绑定手机号
     *
     * @return
     */
    @RequestMapping(value = "/bindPhoneNumber", method = RequestMethod.POST)
    @ApiOperation(value = "小程序绑定手机号")
    @ApiResponses({})
    public ResponseResult<Object> bindPhoneNumber(@RequestBody SysUserVo sysUserVo) {
        // 返回结果
        Map<String, Object> result = Maps.newHashMap();

        if(StringUtils.isBlank(sysUserVo.getUsername())){
            throw new AbortException("手机号不能为空");
        }

        if(!RegexUtils.checkMobile(sysUserVo.getUsername())){
            throw new AbortException("手机号格式错误");
        }

        if (StringUtils.isBlank(sysUserVo.getValidateCode())) {
            throw new AbortException("验证码不能为空");
        }

        if(StringUtils.isBlank(sysUserVo.getWxOpenId())){
            throw new AbortException("openId不能为空");
        }

        SysUser tempUser = new SysUser();
        tempUser.setUsername(sysUserVo.getUsername());

        SysUser user = sysUserService.getOne(tempUser);

        if (user != null && StringUtils.isNotBlank(user.getWxOpenid()) && user.getWxOpenid().equals(sysUserVo.getWxOpenId())) {
            throw new AbortException("不要重复绑定账号");
        }

        if (user != null && StringUtils.isNotBlank(user.getWxOpenid()) && !user.getWxOpenid().equals(sysUserVo.getWxOpenId())) {
            throw new AbortException("该手机号已绑定其他微信号");
        }

        tempUser = new SysUser();
        tempUser.setWxOpenid(sysUserVo.getWxOpenId());
        user = sysUserService.getOne(tempUser);
        if(user==null){
            throw new AbortException("用户不存在");
        }

        if(redisUtils.get(Constant.VALIDATE_CODE+":"+sysUserVo.getUsername())==null){
            throw new AbortException("验证码已过期");
        }

        String sessionValidateCode = redisUtils.get(Constant.VALIDATE_CODE+":"+sysUserVo.getUsername()).toString();

        if (StringUtils.isBlank(sessionValidateCode)) {
            throw new AbortException("验证码已过期");
        }

        if (!sessionValidateCode.equals(sysUserVo.getValidateCode().toUpperCase())) {
            throw new AbortException("验证码输入错误");
        }

        user.setUsername(sysUserVo.getUsername());
        user = sysUserService.changeWxPhone(user);

        redisUtils.del(Constant.VALIDATE_CODE+":"+user.getUsername());
        String token = JwtTokenUtil.generateTerminalUserToken(user);
        result.put("token", token);

        user.setPassword(null);
        result.put("sysUser",user);

        redisUtils.set(Constant.FRONTEND_TOKEN_PRE+":"+user.getUid(), token, Constant.EXPIRATION_TIME);

        //刷新用户登录时间
        user.setLogindate(new Date());
        sysUserService.update(user);

        return ResponseResult.success("授权成功", result);

    }

    /**
     * H5、APP登录接口
     *
     * @return
     */
    @RequestMapping(value = "/loginWithValidateCode", method = RequestMethod.POST)
    @ApiOperation(value = "H5、APP登录接口")
    @ApiResponses({
            @ApiResponse(code = 200, message = "登录成功"),
            @ApiResponse(code = 500, message = "用户已被停用,请联系管理员"),
            @ApiResponse(code = 100101, message = "管理员账号密码错误")
    })
    public ResponseResult<Object> loginWithValidateCode(@RequestBody SysUserVo sysUserVo) {
        // 返回结果
        Map<String, Object> result = Maps.newHashMap();

        if(StringUtils.isBlank(sysUserVo.getUsername())){
            throw new AbortException("手机号不能为空");
        }

        if(!RegexUtils.checkMobile(sysUserVo.getUsername())){
            throw new AbortException("手机号格式错误");
        }

        if (StringUtils.isBlank(sysUserVo.getValidateCode())) {
            throw new AbortException("验证码不能为空");
        }

        SysUser tempUser = new SysUser();
        tempUser.setUsername(sysUserVo.getUsername());

        SysUser user = sysUserService.getOne(tempUser);

        if (user != null && user.getStatus().equals(Constant.USER_STATUS_CLOSE)) {
            throw new AbortException("用户已被停用,请联系管理员");
        }

        if (user != null && user.getStatus().equals(Constant.USER_STATUS_DELETE)) {
            throw new AbortException("对不起,您的账号不存在");
        }

        if(redisUtils.get(Constant.VALIDATE_CODE+":"+sysUserVo.getUsername())==null){
            throw new AbortException("验证码已过期");
        }

        String sessionValidateCode = redisUtils.get(Constant.VALIDATE_CODE+":"+sysUserVo.getUsername()).toString();

        if (StringUtils.isBlank(sessionValidateCode)) {
            throw new AbortException("验证码已过期");
        }

        if (!sessionValidateCode.equals(sysUserVo.getValidateCode().toUpperCase())) {
            throw new AbortException("验证码输入错误");
        }

        //如果user为空，走注册路径
        if(user==null){
            user = new SysUser();
            user.setTopReferralCode(sysUserVo.getTopReferralCode());
            user.setUsername(sysUserVo.getUsername());
            user.setIsFirst(1);
            user.setLogindate(new Date());
            user.setIsEngineer(0);
            user.setLoginVersion(0);
            user.setPoint(BigDecimal.valueOf(new Double(500)));
            user.setStatus(1);
            user.setVip(1);
            user = sysUserService.insert(user);

        }

        redisUtils.del(Constant.VALIDATE_CODE+":"+user.getUsername());
        String token = JwtTokenUtil.generateTerminalUserToken(user);
        result.put("token", token);

        user.setPassword(null);
        result.put("sysUser",user);

        redisUtils.set(Constant.FRONTEND_TOKEN_PRE+":"+user.getUid(), token, Constant.EXPIRATION_TIME);

        //刷新用户登录时间
        user.setLogindate(new Date());
        sysUserService.update(user);


        return ResponseResult.success("登录成功", result);

    }

    /**
     * 刷新token
     *
     * @return
     */
    @RequestMapping(value = "/refreshToken", method = RequestMethod.POST)
    @ApiOperation(value = "刷新token")
    public ResponseResult<Object> refreshToken(HttpServletRequest exchange) throws Exception{
        // 返回结果
        Map<String, Object> result = Maps.newHashMap();

        // 获取 token
        String token = exchange.getHeader("access_token");
        Long id = Long.parseLong(JwtTokenUtil.getIdFromToken(token));
        SysUser sysUser = sysUserService.getById(id);
        if(sysUser == null){
            throw new AbortException("用户不存在");
        }

        String newToken = JwtTokenUtil.generateTerminalUserToken(sysUser);
        result.put("token", newToken);
        result.put("sysUser",sysUser);
        redisUtils.set(Constant.FRONTEND_TOKEN_PRE+":"+sysUser.getUid(), newToken, Constant.EXPIRATION_TIME);
        return ResponseResult.success("授权成功", result);

    }

    /**
     * 修改用户第一次登录终端
     *
     * @return
     */
    @RequestMapping(value = "/changeFirstLogin", method = RequestMethod.POST)
    @ApiOperation(value = "修改用户第一次登录")
    public ResponseResult<Object> changeFirstLogin(HttpServletRequest exchange) throws Exception {

        // 获取 token
        String token = exchange.getHeader("access_token");
        String id = JwtTokenUtil.getIdFromToken(token);
        SysUser sysUser = new SysUser();
        sysUser.setUid(Integer.parseInt(id));
        sysUser.setIsFirst(0);
        int result = sysUserService.changeAttr(sysUser);
        if(result<=0){
            throw new AbortException("修改失败");
        }

        return ResponseResult.success("修改成功");

    }

    /**
     * 注销账号
     *
     * @return
     */
    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    @ApiOperation(value = "用户注销")
    public ResponseResult<Object> logout(HttpServletRequest exchange) throws Exception {

        // 获取 token
        String token = exchange.getHeader("access_token");
        // 删除 token 以注销
        redisUtils.del(Constant.FRONTEND_TOKEN_PRE+":"+JwtTokenUtil.getIdFromToken(token));
        return ResponseResult.success("注销成功");

    }

}
